package com.smartstate.IOC.service.impl;


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.extra.expression.ExpressionUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.smartstate.IOC.dto.EnergyDTO;
import com.smartstate.IOC.dto.PageDTO;
import com.smartstate.IOC.entity.HalfHourPowerMeterSummaryEntity;
import com.smartstate.IOC.mapper.PowerMeterSummaryMapper;
import com.smartstate.IOC.service.ObjMoudelService;
import com.smartstate.IOC.service.PowerMeterSummaryService;
import com.smartstate.IOC.util.MyExpressionUtil;
import com.smartstate.IOC.util.PowerMeterSummaryUtils;
import com.smartstate.IOC.vo.PowerVo;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>能源分析</p>
 * <p>@Author 陈永杰</p>
 * <p>@Date: 2022/9/1</p>
 * <p>@Time: 15:48</p>
 * <p>@version 1.0 <p>
 */
@Service
public class PowerMeterSummaryServiceImpl extends ServiceImpl<PowerMeterSummaryMapper, HalfHourPowerMeterSummaryEntity> implements PowerMeterSummaryService {

    @Resource
    private ObjMoudelService objMoudelService;

    @Resource
    private PowerMeterSummaryMapper powerMeterSummaryMapper;

    private Set<String> deviceIdSet;


    /**
     * 碳足迹
     */
    @Override
    public List<Map<String, Object>> selectCarbonFootprint(EnergyDTO energyDTO) {
        //                        设置小数点不足两位添0格式
        DecimalFormat decimalFormat = new DecimalFormat(".00");
        List<Map<String, Object>> lisAllTree = new ArrayList<>();
        //遍历 拿到设备 电的计算规则
        List<Map<String, String>> stringObjMoudelMap = objMoudelService.selectMetering(energyDTO);
        List<PowerVo> listTree = new ArrayList<>();
        List<PowerVo> listPower = new ArrayList<>();

        HashSet<String> hashSet = new HashSet();

        List<HalfHourPowerMeterSummaryEntity> hfList = powerMeterSummaryMapper.selectDatePrice(energyDTO);
        if (hfList.size() > 0) {
            Map<String, List<HalfHourPowerMeterSummaryEntity>> hfMap = hfList.stream().collect(Collectors.groupingBy(HalfHourPowerMeterSummaryEntity::getMeterId));

            for (Map map : stringObjMoudelMap) {
                String id = (String) map.get("id");
                String parentId = (String) map.get("parentId");
                String name = (String) map.get("name");
                //拿到为电的计算公式
                if (map.get("电") != null && !"".equals(map.get("电"))) {
                    String electricity = (String) map.get("电");
                    energyDTO.setRateType("电");
                    //格式化计算公式
                    String s = MyExpressionUtil.quChu(electricity);
                    //拿到计算公式里的所有deviceId

                    List<String> expressionParams = MyExpressionUtil.getExpressionParams(electricity);
                    //循环拿到deviceId
                    List list = new ArrayList();
                    for (String index : expressionParams) {
                        list.add(index);
                    }
                    energyDTO.setIds(list);

                    List<HalfHourPowerMeterSummaryEntity> resultList = new ArrayList<>(8);
                    expressionParams.forEach(e -> {
                        List<HalfHourPowerMeterSummaryEntity> deviceDataList = hfMap.get(e);
                        if (CollectionUtil.isNotEmpty(deviceDataList)) {
                            resultList.addAll(deviceDataList);
                        }
                    });


//                    collect = resultList.stream().
//                            collect(Collectors.groupingBy(HalfHourPowerMeterSummaryEntity::getDayStr));

                    //查出来所有数据 按时间进行分组
                    Map<String, List<HalfHourPowerMeterSummaryEntity>> collect = resultList.stream().
                            collect(Collectors.groupingBy(HalfHourPowerMeterSummaryEntity::getDayStr));

                    for (Map.Entry<String, List<HalfHourPowerMeterSummaryEntity>> entry : collect.entrySet()) {

                        List<HalfHourPowerMeterSummaryEntity> value = entry.getValue();
                        //树的根节点  第一层的所有时间段数据  一个时间段就代表一个树的根节点
                        HashMap<String, Object> mapWyf = new HashMap<>();
                        HashMap<String, Object> mapCxk = new HashMap<>();

                        HashMap<String, Object> mapLh = new HashMap<>();
                        HashMap<String, Object> mapYy = new HashMap<>();


                        PowerVo powerVo = new PowerVo();
                        String time = "";
                        String rateType = "";

                        //把设备id 对应的能耗放进map  把时间和类型放到对象里
                        for (HalfHourPowerMeterSummaryEntity hs : value) {
                            //费用
                            mapLh.put(hs.getMeterId(), hs.getTotalPrice());
                            //能耗
                            mapWyf.put(hs.getMeterId(), hs.getDetActiveEnergy());

                            time = hs.getDayStr();
                            rateType = hs.getRateType();
                            hashSet.add(hs.getDayStr());

                        }
                        //把设备id拼接ll 对应能耗放进对应id里 有设备id的 没有能耗的放0
                        //[DHU0011,DHU0012]
                        //map{"DHU0012","123321"}
                        for (Object ls : list) {
                            for (Map.Entry<String, Object> stringObjectEntry : mapWyf.entrySet()) {
                                if (!ls.equals(stringObjectEntry.getKey())) {
                                    mapCxk.put("LL" + ls, 0);

                                }
                                if (ls.equals(stringObjectEntry.getKey())) {
                                    mapCxk.put("LL" + ls, stringObjectEntry.getValue());
                                    break;
                                }
                            }
                        }

                        //把设备id拼接ll 对应费率放进对应id里 有设备id的 没有费率的放0
                        //[DHU0011,DHU0012]
                        //map{"DHU0012","123321"}
                        for (Object ls : list) {
                            for (Map.Entry<String, Object> stringObjectEntry : mapLh.entrySet()) {
                                if (!ls.equals(stringObjectEntry.getKey())) {
                                    mapYy.put("LL" + ls, 0);

                                }
                                if (ls.equals(stringObjectEntry.getKey())) {
                                    mapYy.put("LL" + ls, stringObjectEntry.getValue());
                                    break;
                                }
                            }
                        }

                        //{"llDHU0012+llDHU0011",{LLDHU0012:123},{LLDHU0011:0}}
                        //把上面的公式 和 map放进方法 算出能耗值
                        Float num = Float.parseFloat(ExpressionUtil.eval(s, mapCxk).toString());
                        //费率
                        Float price = Float.parseFloat(ExpressionUtil.eval(s, mapYy).toString());

                        //平均价
                        Float rate = 0.00F;
                        if (num > 0 && price > 0) {
                            rate = (price / num);
                        }
                        // 碳足迹
                        double carbon = 0.00F;
                        if (num > 0) {
                            carbon = num * 0.785;
                        }
                        //保留小数点两位，采用截断模式
                        num = new BigDecimal(num).setScale(2, RoundingMode.DOWN).floatValue();
                        price = new BigDecimal(price).setScale(2, RoundingMode.DOWN).floatValue();
                        rate = new BigDecimal(rate).setScale(2, RoundingMode.DOWN).floatValue();

                        //小数点不足两位添0
                        String numStr = decimalFormat.format(num);
                        String rates = decimalFormat.format(rate);
                        String prices = decimalFormat.format(price);
                        //把所有需要的值全放入powerVo这个对象
                        //碳足迹
                        powerVo.setCarbon(carbon);
                        //把所有需要的值全放入powerVo这个对象
                        powerVo.setRate(rates);
                        powerVo.setNum(numStr);
                        powerVo.setPrice(prices);
                        powerVo.setRateType(rateType);
                        powerVo.setId(id);
                        powerVo.setParentId(parentId);
                        powerVo.setName(name);
                        powerVo.setTime(time);
                        powerVo.setGraininess(energyDTO.getGraininess());

                        //我这个 listTree 已经是分好组的 数据 就是要遍历 这个 listTree 找出父子级关系 然后 比对时间  如果是父子级id 就比较
                        listTree.add(powerVo);
                    }
                } else {
                    PowerVo powerVo = new PowerVo();
                    //把判断颗粒度时没有 计算公式的放到这个对象集合里
                    powerVo.setId(id);
                    powerVo.setParentId(parentId);
                    powerVo.setName(name);

                    powerVo.setGraininess(energyDTO.getGraininess());
                    //我这个 listTree 已经是分好组的 数据 就是要遍历 这个 listTree 找出父子级关系 然后 比对时间  如果是父子级id 就比较
                    listPower.add(powerVo);
                }
                if (listPower.size() > 0) {
                    for (PowerVo powerVo : listPower) {
                        for (String setTime : hashSet) {
                            PowerVo powerVo1 = new PowerVo();
                            powerVo1.setId(powerVo.getId());
                            powerVo1.setParentId(powerVo.getParentId());
                            powerVo1.setGraininess(powerVo.getGraininess());
                            powerVo1.setRateType("");
                            powerVo1.setCarbon(0.00);
                            powerVo1.setName(powerVo.getName());
                            powerVo1.setTime(setTime);
                            listTree.add(powerVo1);
                        }
                    }
                }
            }


            Map<String, Double> collect = listTree.stream().collect(Collectors.groupingBy(PowerVo::getId, Collectors.summingDouble(PowerVo::getCarbon)));
            PowerMeterSummaryUtils ps = new PowerMeterSummaryUtils();
            lisAllTree = ps.CrbonPwerTree(collect, energyDTO);
            return lisAllTree;
        }
        return null;
    }

    @Override
    public Page<HalfHourPowerMeterSummaryEntity> queryAllPageByDTO(PageDTO pageDTO) {
        return null;
    }
}

